﻿/*=============================================================================
* File Name : Vector3.h                         Ver : 1.00  Date : 2009-3-17
*
* Description :
*
*       3Dベクトル計算　ヘッダ
*
* Author : 土田　悠貴.
*============================================================================*/
#ifndef _VECTOR3_H_
#define _VECTOR3_H_

namespace tglib
{

class Vector2;
class Vector4;
class Matrix3;
class Matrix4;

/**
 * @brief 3Dベクトル計算クラス．
 */
class Vector3
{
public:
	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 */
	Vector3();

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]     X　X座標．
	 * @param [in]     Y　Y座標．
	 * @param [in]     Z　Z座標．
	 */
	Vector3( float X, float Y, float Z );

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]     v2　2Dベクトル．
	 * @param [in]     Z　 Z座標．
	 */
	Vector3( const Vector2& v2, float Z = 0.0f );

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]     v4　四次元ベクトル．
	 */
	Vector3( const Vector4& v4 );

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]     p　配列のポインタ．
	 */
	Vector3( const float* p );

	/*===========================================================================*/
	/**
	 * 正規化．
	 *
	 * @return 正規化したベクトル．
	 */
	Vector3& normalize();

	/*===========================================================================*/
	/**
	 * 正規化したベクトルを取得する．
	 *
	 * @return 正規化したベクトル．
	 */
	Vector3 getNormalized() const;

	/*===========================================================================*/
	/**
	 * 長さを求める．
	 *
	 * @return 長さ ．
	 */
	float length() const;

	/*===========================================================================*/
	/**
	 * 長さを求める (２乗和のみ）．
	 *
	 * @return 長さ(２乗和）．
	 */
	float lengthSq() const;

	/*===========================================================================*/
	/**
	 * 距離を求める．
	 *
	 * @param [in]  V 3Dベクトル ．
	 * @return 距離 ．
	 */
	float distance( const Vector3& V ) const;

	/*===========================================================================*/
	/**
	 * 内積を求める．
	 *
	 * @param [in]  V 3Dベクトル ．
	 * @return 内積 ．
	 */
	float dot( const Vector3& V ) const;

	/*===========================================================================*/
	/**
	 * 外積を求める．
	 *
	 * @param [in]  V 3Dベクトル ．
	 * @return 外積 ．
	 */
	Vector3 cross( const Vector3& V ) const;

	/*===========================================================================*/
	/**
	 * 小さい要素を求める．
	 *
	 * @param [in]  V 3Dベクトル ．
	 * @return 小さい要素 ．
	 */
	Vector3 minimize( const Vector3& V ) const;

	/*===========================================================================*/
	/**
	 * 大きい要素を求める．
	 *
	 * @param [in]  V 3Dベクトル ．
	 * @return 大きい要素 ．
	 */
	Vector3 maximize( const Vector3& V ) const;

	/*===========================================================================*/
	/**
	 * 線形補間を行う．
	 *
	 * @param [in]  min 最小値 ．
	 * @param [in]  max 最大値 ．
	 * @param [in]  t 補間地(0.0～1.0) ．
	 * @return 補間した3Dベクトル ．
	 */
	Vector3& lerp( const Vector3& min, const Vector3& max, float t );

	/*===========================================================================*/
	/**
	 * 二次補間を行う．
	 *
	 * @param [in]  v1 補間要素3次元ベクトル.
	 * @param [in]  v2 補間要素3次元ベクトル.
	 * @param [in]  v3 補間要素3次元ベクトル.
	 * @param [in]  t 補間値( 0.0f～1.0f ).
	 * @return 補間した3Dベクトル ．
	 */
	Vector3& quadratic(const Vector3& v1, const Vector3& v2, const Vector3& v3, float t);

	/*===========================================================================*/
	/**
	 * 反射ベクトルを求める ．
	 *
	 * @param [in]  N 法線ベクトル ．
	 * @return 反射ベクトル ．
	 */
	Vector3 reflect( const Vector3& N ) const;

	/*===========================================================================*/
	/**
	 * 屈折ベクトルを求める．
	 *
	 * @param [in]  N 　法線ベクトル ．
	 * @param [in]  Eta 屈折比率 ．
	 * @return 屈折ベクトル ．
	 */
	Vector3 refract( const Vector3& N, float Eta ) const;

	/*===========================================================================*/
	/**
	 * ２つベクトルのなす角度を求める．
	 *
	 * @param [in]  V　3Dベクトル ．
	 * @return 角度 ．
	 */
	float degree( const Vector3& V ) const;

	/*===========================================================================*/
	/**
	 * ヨーを求める．
	 *
	 * @return ヨー ．
	 */
	float getYaw() const;

	/*===========================================================================*/
	/**
	 * ピッチを求める．
	 *
	 * @return ピッチ．
	 */
	float getPitch() const;

	/*===========================================================================*/
	/**
	 * ピッチ・ヨーからベクトルを求める．
	 *
	 * @param [in]  picth　ピッチ．
	 * @param [in]  yow　  ヨー．
	 * @return 3Dベクトル．
	 */
	Vector3& fromPitchYaw( float picth, float yow );

	/*===========================================================================*/
	/**
	 * 法線ベクトルを求める．
	 *
	 * @param [in]  V1　三角形の頂点座標．
	 * @param [in]  V2　三角形の頂点座標．
	 * @return 法線ベクトル．
	 */
	Vector3 calculateNormal( const Vector3& V1, const Vector3& V2 ) const;

	/*===========================================================================*/
	/**
	 * 直線の方程式の計算を行う．
	 *
	 * @param [in]  V1　3Dベクトル．
	 * @param [in]  V2　3Dベクトル．
	 * @param [in]  t　 係数．
	 * @return 結果．
	 */
	Vector3& linearEquation( const Vector3& V1, const Vector3& V2, float t );

	/*===========================================================================*/
	/**
	 * (float*型)キャスト演算子オーバーロード．
	 *
	 * @return   型変換をしたXYZ成分．
	 */
	operator float* ();

	/*===========================================================================*/
	/**
	 * (const float*型)キャスト演算子オーバーロード．
	 *
	 * @return   型変換をしたXYZ成分．
	 */
	operator const float* ();

	/*===========================================================================*/
	/**
	 * (+)単項演算子オーバーロード．
	 *
	 * @return 結果のVector3．
	 */
	Vector3  operator + () const;

	/*===========================================================================*/
	/**
	 * (-)単項演算子オーバーロード．
	 *
	 * @return 結果のVector3.
	 */
	Vector3  operator - () const;

	/*===========================================================================*/
	/**
	 * (+=) 演算子オーバーロード．
	 * 
	 * @param [in]  v Vector3．
	 * @return 結果のVector3．
	 */
	Vector3&  operator += ( const Vector3& v );

	/*===========================================================================*/
	/**
	 * (-=) 演算子オーバーロード．
	 * 
	 * @param [in]  v Vector3．
	 * @return 結果のVector3．
	 */
	Vector3&  operator -= ( const Vector3& v );

	/*===========================================================================*/
	/**
	 * (*=) 演算子オーバーロード．
	 * 
	 * @param [in]  v Vector3．
	 * @return 結果のVector3．
	 */
	Vector3&  operator *= ( const Vector3& v );

	/*===========================================================================*/
	/**
	 * (/=) 演算子オーバーロード．
	 * 
	 * @param [in]  v Vector3．
	 * @return 結果のVector3．
	 */
	Vector3&  operator /= ( const Vector3& v );

	/*===========================================================================*/
	/**
	 * (*=) 演算子オーバーロード．
	 * 
	 * @param [in]  s スカラー．
	 * @return 結果のVector3．
	 */
	Vector3&  operator *= ( float s );

	/*===========================================================================*/
	/**
	 * (/=) 演算子オーバーロード．
	 * 
	 * @param [in]  s スカラー．
	 * @return 結果のVector3．
	 */
	Vector3&  operator /= ( float s );
	
public:
	union
	{
		struct
		{
			/** @brief x座標 */
			float x;	

			/** @brief y座標 */
			float y;	

			/** @brief z座標 */
			float z;	
		};

		/** @brief xyz座標 */
		float XYZ[3];
	};

};

/***  以下非メンバ関数 *******************************************************/

/*===========================================================================*/
/**
 * (+)演算子オーバーロード．
 * 
 * @param [in]  v1 Vector3．
 * @param [in]  v2 Vector3．
 * @return 結果のVector3．
 */
const Vector3 operator + ( const Vector3& v1, const Vector3& v2 );

/*===========================================================================*/
/**
 * (-)演算子オーバーロード．
 * 
 * @param [in]  v1 Vector3．
 * @param [in]  v2 Vector3．
 * @return 結果のVector3．
 */
const Vector3 operator - ( const Vector3& v1, const Vector3& v2 );

/*===========================================================================*/
/**
 * (*)演算子オーバーロード．
 * 
 * @param [in]  v1 Vector3．
 * @param [in]  v2 Vector3．
 * @return 結果のVector3．
 */
const Vector3 operator * ( const Vector3& v1, const Vector3& v2 );

/*===========================================================================*/
/**
 * (*)演算子オーバーロード．
 * 
 * @param [in]  v Vector3．
 * @param [in]  s スカラー．
 * @return 結果のVector3．
 */
const Vector3 operator * ( const Vector3& v, const float s );

/*===========================================================================*/
/**
 * (*)演算子オーバーロード．
 * 
 * @param [in]  s スカラー．
 * @param [in]  v Vector3．
 * @return 結果のVector3．
 */
const Vector3 operator * ( const float s, const Vector3& v );


/*===========================================================================*/
/**
 * (*)演算子オーバーロード(座標変換)．
 * 
 * @param [in]  m Matrix4．
 * @param [in]  v Vector3．
 * @return 結果のVector3．
 */
const Vector3 operator * ( const Matrix4& m, const Vector3& v );

/*===========================================================================*/
/**
 * (*)演算子オーバーロード(座標変換)．
 * 
 * @param [in]  v Vector3．
 * @param [in]  m Matrix4．
 * @return 結果のVector3．
 */
const Vector3 operator * ( const Vector3& v, const Matrix4& m );

/*===========================================================================*/
/**
 * (/)演算子オーバーロード．
 * 
 * @param [in]  v1 Vector3．
 * @param [in]  v2 Vector3．
 * @return 結果のVector3．
 */
const Vector3 operator / ( const Vector3& v1, const Vector3& v2 );

/*===========================================================================*/
/**
 * (/)演算子オーバーロード．
 * 
 * @param [in]  v Vector3．
 * @param [in]  s スカラー．
 * @return 結果のVector3．
 */
const Vector3 operator / ( const Vector3& v, float s );

/*===========================================================================*/
/**
 * (/)演算子オーバーロード．
 * 
 * @param [in]  s スカラー．
 * @param [in]  v Vector3．
 * @return 結果のVector3．
 */
const Vector3 operator / ( float s, const Vector3& v );

/*===========================================================================*/
/**
 * (==) 演算子オーバーロード．
 * 
 * @param [in]  v1 Vector3．
 * @param [in]  v2 Vector3．
 * @return 比較結果．
 */
bool operator == ( const Vector3& v1, const Vector3& v2 );

/*===========================================================================*/
/**
 * (!=) 演算子オーバーロード．
 * 
 * @param [in]  v1 Vector3．
 * @param [in]  v2 Vector3．
 * @return 比較結果．
 */
bool operator != ( const Vector3& v1, const Vector3& v2 );

/*===========================================================================*/
/**
 * (<) 演算子オーバーロード．
 * 
 * @param [in]  v1 Vector3．
 * @param [in]  v2 Vector3．
 * @return 比較結果．
 */
bool operator < ( const Vector3& v1, const Vector3& v2 );

/*===========================================================================*/
/**
 * (>) 演算子オーバーロード．
 * 
 * @param [in]  v1 Vector3．
 * @param [in]  v2 Vector3．
 * @return 比較結果．
 */
bool operator > ( const Vector3& v1, const Vector3& v2 );

/*===========================================================================*/
/**
 * (<=) 演算子オーバーロード．
 * 
 * @param [in]  v1 Vector3．
 * @param [in]  v2 Vector3．
 * @return 比較結果．
 */
bool operator <= ( const Vector3& v1, const Vector3& v2 );

/*===========================================================================*/
/**
 * (>=) 演算子オーバーロード．
 * 
 * @param [in]  v1 Vector3．
 * @param [in]  v2 Vector3．
 * @return 比較結果．
 */
bool operator >= ( const Vector3& v1, const Vector3& v2 );

} // namespace tglib

#endif

/*========= End of File =====================================================*/
